package main

import "fmt"

func main17() {
	// 无缓冲channel 交互模式类似于无空间的 synchronizedQueue
	/*c := make(chan int)
	go func() {
		fmt.Println("goroutine start...")
		fmt.Println("set c: ", 666)

		// 赋值到channel中  这里如果比获取快的话会先阻塞在这里
		c <- 666
		fmt.Println("goroutine end...")
	}()
	fmt.Println("before get from channel...")
	// 从channel获取 会阻塞等待
	num := <-c
	fmt.Println("get c: ", num)
	fmt.Println("after get from channel...")*/

	// 有缓冲的channel 类似于blockingqueue  满了生产者阻塞  空了消费者阻塞
	/*c := make(chan int, 3)

	go func() {
		defer fmt.Println("子go程结束")
		// 发送到第四个的时候会阻塞  直到主线程取出第一个才能发最后一个
		// 第四次发送一定是在第一次获取之后
		for i := 0; i < 4; i++ {
			c <- i + 1
			fmt.Println(i+1, " sended...")
		}
	}()
	time.Sleep(2 * time.Second)
	for i := 0; i < 4; i++ {
		num := <-c // 箭头和c之间不能有空格
		fmt.Println(num, " getted...")
	}
	time.Sleep(2 * time.Second)*/

	// channel 必须关闭从而避免死等待
	c := make(chan int, 3)

	go func() {
		defer fmt.Println("go routine end...")
		// channel 必须关闭从而避免死等待
		defer close(c)
		for i := 0; i < 3; i++ {
			c <- i + 1
			// 向关闭了的channel发数据会报错  但是接收不会
			// close(c)
		}
	}()

	/*for {
		// 如果不关闭channel  这里的for中会死等看是否ok
		if v, ok := <-c; ok {
			fmt.Println(v)
		} else {
			break
		}
	}*/

	// 以下语法糖等价上面的for死循环 会判断是否ok
	for data := range c {
		fmt.Println(data)
	}
	fmt.Println("main end...")

}
